from django.http import HttpResponse
from django.conf import settings
from django.core.cache import cache
from django.utils import timezone

import json, jwt, time, datetime
# from datetime import datetime

from ...models.users import Users
from ...models.chat_loginlog import LoginLog
from ...models.configs import Configs

from ...utils.users import generate_salt, create_password_hash, get_login_user_id
from ...utils.data_handle import users_data_paging, query_ip_location


def register(request):
    '''
    注册
    post
    数据：{
        "username": "test2",
        "password": "12345678",
        "code": "",
        "repass": "12345678",
        "reg_way": "username"
    }
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)
        upass = json_obj['password']

        if len(upass) < 8:
            res_mes = {
                "code": 1,
                "message": "密码长度不能少于8个字符"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        uname = json_obj['username']
        re_user_obj = Users.objects.filter(username=uname)
        if re_user_obj:
            res_mes = {
                "code": 1,
                "message": "该用户名已经被注册"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json) 

        # 检查验证码
        if json_obj['reg_way'] == "email" or json_obj['reg_way'] == "mobile":
            code_store_prefix = "/verify/codes/{}".format(json_obj['username'])
            cache_code = cache.get(code_store_prefix)
            if not int(cache_code) == int(json_obj['code']):
                res_mes = {
                    "code": 1,
                    "message": "验证码错误"
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json) 

        # 验证邀请码，暂时留着 PASS

        # 生成加密盐
        salt = generate_salt(8)
        chat_config_json = Configs.objects.get(marker="system").config_json
        default_models = chat_config_json['default_models']
        default_power = chat_config_json['init_power']

        # 创建用户
        users_instance = Users()
        json_obj_users_linshi = {
            "username": uname,
            "password": create_password_hash(upass, salt),
            "nickname": "暂无昵称",
            "salt": salt,
            "power": default_power,
            "chat_config_json": None,
            "chat_roles_json": "[\"gpt\"]",
            "chat_models_json": default_models,
            "vip": False
        }
        for key, value in json_obj_users_linshi.items():
            code_str = "users_instance.%s = '%s'" % (key, value)
            exec(code_str)

        try:
            users_instance.save()
        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "创建用户失败！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 注册成功 删除短信验证码
        cache.delete(code_store_prefix)

        # 自动登录创建 token
        now_time = time.time()
        expired_time = now_time + settings.MY_TOKEN_CONF['MAXAGE']
        payload_json = {
            "user_id": users_instance.id,
            "username": users_instance.username,
            "expired": expired_time
        }
        # 加密
        try:
            token_str = jwt.encode(payload_json, settings.MY_TOKEN_CONF['SECRETKEY'])
        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "Failed to generate token：{e}"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        # 解密
        # jwt.decode(token_str, settings.MY_TOKEN_CONF['SECRETKEY'], algorithms=['HS256'])

        # 把token存入redis
        mes_key = "users/%s" % users_instance.id
        try:
            cache.set(mes_key, token_str, timeout=settings.MY_TOKEN_CONF['MAXAGE'])
        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "Failed to generate token：{e}"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        res_mes = {
            "code": 0,
            "data": token_str
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)


def login(request):
    '''
    登陆
    post
    body = {
        "username": "fanlichun",
        "password": "12345678",
        "code": "12345678", 验证码
        "activename: password|mobile" 登陆方式
    }
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)

        uname = json_obj['username']
        upass = json_obj['password']
        ucode = json_obj['code']
        activename = json_obj['activename']


        # 先获取这个用户的信息，检查是否有这个用户
        try:
            re_user_obj_list = Users.objects.filter(username=uname).order_by('id')
            if re_user_obj_list:
                re_user_obj = re_user_obj_list[0]
            else:
                res_mes = {
                    "code": 1,
                    "message": "用户名不存在"
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
        except Users.DoesNotExist:
            res_mes = {
                "code": 1,
                "message": "用户名不存在"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)


        # 判断用户是密码登陆还是验证码登陆
        if activename == "password":
            # 如果用户选择的是密码登陆，就验证密码
            login_pass = create_password_hash(upass, re_user_obj.salt)
            if login_pass != re_user_obj.password:
                res_mes = {
                    "code": 1,
                    "message": "用户名或密码错误"
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
        elif activename == "mobile":
            # 如果用户选择的是短信登陆 就验证 验证码是否正常
            code_store_prefix = "/verify/codes/{}".format(json_obj['username'])
            cache_code = cache.get(code_store_prefix)
            if cache_code is None:
                res_mes = {
                    "code": 1,
                    "message": "验证码错误"
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
            if not int(cache_code) == int(json_obj['code']):
                res_mes = {
                    "code": 1,
                    "message": "验证码错误"
                }
                res_mes_json = json.dumps(res_mes, ensure_ascii=False)
                return HttpResponse(res_mes_json)
        else:
            # 如果都不是这两种登陆方式的话 那就是违规登陆
            res_mes = {
                "code": 1,
                "message": "请选择有效的登陆方式"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
            

        if not re_user_obj.status:
            res_mes = {
                "code": 1,
                "message": "该用户已被禁止登录，请联系管理员"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        ###########################################
        # 判断用户是否在有效期内
        # 并且用户组的有效期大于 用户有效期
        # print(re_user_obj.expired_time, '过期时间')

        # 查询用户是否有绑定用户组
        ################################################################
        # all_usergroup_obj = re_user_obj.userList.all()
        # if all_usergroup_obj:
        #     # 如果要是绑定了用户组, 过期时间就以用户组为优先
        #     one_usergroup_obj = all_usergroup_obj[0]
        #     if one_usergroup_obj.user_expired_time is not None or one_usergroup_obj.user_expired_time:
        #         dt_naive = one_usergroup_obj.user_expired_time.replace()
        #         if dt_naive < datetime.datetime.now().replace(tzinfo=datetime.timezone.utc):
        #             res_mes = {
        #                 "code": 1,
        #                 "message": "您的账号已经过期，请联系管理员！"
        #             }
        #             res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        #             return HttpResponse(res_mes_json)
        # else:
        #     # 如果没有绑定了用户组, 过期时间就以用户为优先
        #     if re_user_obj.expired_time is not None or re_user_obj.expired_time:
        #         dt_naive = re_user_obj.expired_time.replace()
        #         if dt_naive < datetime.datetime.now().replace(tzinfo=datetime.timezone.utc):
        #             res_mes = {
        #                 "code": 1,
        #                 "message": "您的账号已经过期，请联系管理员！"
        #             }
        #             res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        #             return HttpResponse(res_mes_json)
        ################################################################


        # 创建 token
        now_time = time.time()
        expired_time = now_time + settings.MY_TOKEN_CONF['MAXAGE']
        payload_json = {
            "user_id": re_user_obj.id,
            "username": re_user_obj.username,
            "expired": expired_time,
            "isadminapi": False
        }
        # 加密
        try:
            token_str = jwt.encode(payload_json, settings.MY_TOKEN_CONF['SECRETKEY'])
        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "Failed to generate token：{e}"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 把token存入redis
        mes_key = "users/%s" % re_user_obj.id
        try:
            cache.set(mes_key, token_str, timeout=settings.MY_TOKEN_CONF['MAXAGE'])
        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "Failed to generate token：{e}"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 更新最后登录时间和IP
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            client_ip = x_forwarded_for.split(',')[0]
        else:
            client_ip = request.META.get('REMOTE_ADDR')

        re_user_obj.last_login_ip = client_ip
        # 更新登陆的ip地址信息
        ip_info = query_ip_location(client_ip)
        if ip_info:
            login_ip_info = "{}-{}-{}".format(ip_info['country_name'], ip_info['province_name'], ip_info['city_name'])
        else:
            login_ip_info = "0-0-内网IP"
        re_user_obj.last_login_at = datetime.datetime.now()
        
        # 更新数据
        try:
            re_user_obj.save()
        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "保存登陆数据失败！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 当登陆成功后 删除缓存的验证码
        # 注册成功 删除短信验证码
        if activename == "mobile":
            cache.delete(code_store_prefix)


        # 记录一条登陆日志
        loginlog_instance = LoginLog()
        loginlog_instance.user_id = re_user_obj.id
        loginlog_instance.username = re_user_obj.username
        loginlog_instance.login_ip = client_ip
        loginlog_instance.login_address = login_ip_info

        # 更新数据
        try:
            loginlog_instance.save()
        except:
            print('登陆日志记录失败')
            pass

        # 缓存用户信息
        chatusers_tree_json = users_data_paging(re_user_obj_list, 1, 20)

        # 设置用户信息缓存到redis
        cache.set("user_info_{}".format(re_user_obj.id), chatusers_tree_json["items"][0], timeout=3600)  # 设置缓存超时时间为3600秒


        # # 设置request属性
        # request.session["LOGIN_USER_ID"] = re_user_obj.id
        
        res_mes = {
            "code": 0,
            "data": token_str
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)


def users_session(request):
    '''
    session 会话检测
    '''
    # 先查询 user_id
    userid = get_login_user_id(request, isadmin=False)
    # print(userid, "会话检测")
    if not userid:
        res_mes = {
            "code": 1,
            "message": "用户没有登陆!"
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)
    
    # 先从redis缓存中获取用户信息
    ## 暂时关闭
    user_cache_mes = cache.get(f'user_info_{userid}')
    if user_cache_mes:
        res_mes = {
           "code": 0,
           "data": user_cache_mes
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)

    # 在redis查询user token信息
    mes_key = "users/%s" % userid
    try:
        cache.get(mes_key)
    except Exception as e:
        res_mes = {
            "code": 1,
            "message": "redis 没有登陆记录!"
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)
    
    # 获取用户信息
    try:
        re_user_obj = Users.objects.filter(id=userid).order_by('id')

        # 设置用户信息缓存到redis
        chatusers_tree_json = users_data_paging(re_user_obj, 1, 10)
        cache.set(f'user_info_{userid}', chatusers_tree_json["items"][0], timeout=3600)  # 设置缓存超时时间为3600秒

        res_mes = {
            "code": 0,
            "data": chatusers_tree_json['items'][0]
        }

        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)
    except Users.DoesNotExist:
        res_mes = {
            "code": 1,
            "message": "用户名不存在!"
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)


def logout(request):
    '''
    退出会话
    '''
    userid = get_login_user_id(request, isadmin=False)
    mes_key = "users/%s" % userid
    # 删除单个key
    try:
        cache.delete(mes_key)
    except Exception as e:
        res_mes = {
            "code": 1,
            "message": "退出登陆失败！"
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)
    
    # 返回数据
    res_mes = {
        "code": 0
    }
    res_mes_json = json.dumps(res_mes, ensure_ascii=False)
    return HttpResponse(res_mes_json)


def profile(request):
    '''
    用户简介
    '''
    # 先查询 user_id
    userid = get_login_user_id(request, isadmin=False)
    if not userid:
        res_mes = {
            "code": 1,
            "message": "用户没有登陆!"
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)

    # 先从redis缓存中获取用户信息
    user_cache_mes = cache.get(f'user_info_{userid}')
    if user_cache_mes:
        res_mes = {
           "code": 0,
           "data": user_cache_mes
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json) 
    
    re_user_obj = Users.objects.filter(id=userid).order_by('id')
    chatusers_tree_json = users_data_paging(re_user_obj, 1, 10)
    res_mes = {
        "code": 0,
        "data": chatusers_tree_json['items'][0]
    }

    res_mes_json = json.dumps(res_mes, ensure_ascii=False)
    return HttpResponse(res_mes_json)


def profile_update(request):
    '''
    用户更新昵称
    post
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)

        re_nickname = json_obj['nickname']
        userid = json_obj['id']

        try:
            Users.objects.filter(id=userid).update(nickname=re_nickname)

        except Exception as e:
            res_mes = {
                "code": 1,
                "message": "保存昵称失败！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 更新redis的缓存
        # 先看看redis有没有缓存，有的话 再更新
        user_cache_mes = cache.get(f'user_info_{userid}')
        if user_cache_mes:
            user_cache_mes['nickname'] = re_nickname
            cache.set(f'user_info_{userid}', user_cache_mes, timeout=3600)

        res_mes = {
            "code": 0
        }
        res_mes_json = json.dumps(res_mes, ensure_ascii=False)
        return HttpResponse(res_mes_json)


def users_password(request):
    '''
    修改密码
    POST
    re = {
        "old_pass": "12345678",
        "password": "12345678",
        "repass": "12345678"
    }
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)

        old_pass = json_obj['old_pass']
        new_pass = json_obj['password']

        # 判断新密码长度
        if len(new_pass) < 8:
            res_mes = {
                "code": 1,
                "message": "密码长度不能少于8个字符！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 先查询 user_id
        userid = get_login_user_id(request, isadmin=False)
        if not userid:
            res_mes = {
                "code": 1,
                "message": "用户没有缓存id!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 获取用户实例
        try:
            re_user_obj = Users.objects.get(id=userid)
        except:
            res_mes = {
                "code": 1,
                "message": "没有这个用户!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 查看原密码是否正确
        old_pass_hash = create_password_hash(old_pass, re_user_obj.salt)
        if old_pass_hash != re_user_obj.password:
            res_mes = {
                "code": 1,
                "message": "原密码错误!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        if old_pass == new_pass:
            res_mes = {
                "code": 1,
                "message": "修改失败！与原密码一样!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)

        
        try:
            new_pass_hash = create_password_hash(new_pass, re_user_obj.salt)
            re_user_obj.password = new_pass_hash
            re_user_obj.save()

            res_mes = {
                "code": 0
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        except:
            res_mes = {
                "code": 1,
                "message": "密码更新失败!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)


def users_password_bind(request):
    '''
    重置账号
    占位
    '''
    pass


def users_resetpass(request):
    '''
    重制密码
    post
    body = {
        "username": 182014199665,
        "code": "321123"          # 验证码
        "password": "11111111"    # 新密码
    }
    '''
    if request.method == 'POST':
        json_b = request.body
        json_str = json_b.decode('utf-8')
        json_obj = json.loads(json_str)

        new_password = json_obj['password']
        # 判断新密码长度
        if len(new_password) < 8:
            res_mes = {
                "code": 1,
                "message": "密码长度不能少于8个字符！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 获取用户实例
        try:
            re_user_obj = Users.objects.get(username=json_obj['username'])
        except:
            res_mes = {
                "code": 1,
                "message": "没有这个用户!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 检查验证码
        code_store_prefix = "/verify/codes/{}".format(json_obj['username'])
        cache_code = cache.get(code_store_prefix)
        if cache_code is None:
            res_mes = {
                "code": 1,
                "message": "验证码失效！"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        if not int(cache_code) == int(json_obj['code']):
            res_mes = {
                "code": 1,
                "message": "验证码错误"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        
        # 更新密码
        new_pass_hash = create_password_hash(new_password, re_user_obj.salt)
        try:
            re_user_obj.password = new_pass_hash
            re_user_obj.save()

            # 注册成功 删除短信验证码
            cache.delete(code_store_prefix)

            res_mes = {
                "code": 0
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)
        except:
            res_mes = {
                "code": 1,
                "message": "密码更新失败!"
            }
            res_mes_json = json.dumps(res_mes, ensure_ascii=False)
            return HttpResponse(res_mes_json)

